// 验证服务器的有效性
/**
 * 1. 微信服务气要知道开发者服务器
 * 2. 测试号 填写的服务器地址
 *  - 使用ngrok内网穿透
 *  http://32508ddc.ngrok.io // 内网穿透
 *  ./ngrok http 3000 // 运行ngrok
 *
 *
 3. 验证消息是否来自微信服务器
 1、 将参与微信加密签名的三个参数（timestamp，nonce，token）按照字典顺序排序并组合在一起形成一个数组
 2、 将数组里所有参数拼装成一个字符串，进行sha1加密
 3、 加密完成就生成一个signatrue，和微信发送过来的进行对比
 - 如果一样，说明消息来自微信，返回echostr给微信服务器
 - 如果不一样， 说明不是微信服务器发送的信息，返回error
 */

/**
 * 验证服务器有效性
 * 中间件函数
 * @returns {Function}
 */

// 引入config模块
const config = require('../config');

console.info(config)
// 引入sha1 模块
const sha1 = require('sha1');

// 引入tool模块
const {getUserDataAsync, parseXMLAsync, formatMessage} = require('../utils/tool.js');

// 引入template模块
const template = require('./template');

// 引入reply模块
const reply = require('./reply');


module.exports = ()=> {
    return async (req, res, next) => {

        const {signature, echostr, timestamp, nonce} = req.query;
        const {token} = config;
        const sha1Str = sha1([timestamp, nonce, token].sort().join(''));

        /**
         * 微信服务器会发送两种类型的消息给开发者服务器
         * 1. GET请求
         *  - 验证服务器的有效性
         * 2. POST请求
         *  - 微信服务器 会将用户发送的数据以POST的方式转发到开发者服务器
         *
         */
        // 1按字典顺序排放
        // const arr = [timestamp, nonce, token];
        // const arrSort = arr.sort();
        // console.log(arrSort);
        // // 2加密
        // const str = arr.join('');
        // const sha2Str = sha1(str);
        // console.log(sha1Str);
        // // 3对比
        // console.log(sha2Str === signature)


        if (req.method === 'GET') {
            if (sha1Str === signature) {
                res.send(echostr)
            } else {
                res.end('error');
            }

        } else if (req.method === 'POST') {
            if (sha1Str !== signature) {
                // 说明消息不是来自微信服务器
                res.send('error');
            }

            console.log(req.query);
            // 接受请求体中的数据， 流式数据
            const xmlData = await getUserDataAsync(req); // promise对象then方法的替代方案await
            console.log(xmlData);
            /*<xml><ToUserName><![CDATA[gh_4f14f825bf00]]></ToUserName> // 开发者id
            <FromUserName><![CDATA[oVMRi5lqzzd7Qisq7HId9YDX8on4]]></FromUserName>  // 用户的openid
            <CreateTime>1560741296</CreateTime> // 发送的时间戳
            <MsgType><![CDATA[text]]></MsgType> // 发送消息类型
            <Content><![CDATA[哈利路亚]]></Content> // 发送的内容
            <MsgId>22344442298674710</MsgId> // 消息id 微信服务器默认保存3点用户发送的数据， 通过此id三天内就能找到消息数据，三天后被销毁
            </xml>*/


            // 将xml数据解析为js对象
            const jsData = await parseXMLAsync(xmlData);
            console.log(jsData);
            /*{
                xml:{
                    ToUserName: [ 'gh_4f14f825bf00' ],
                    FromUserName: [ 'oVMRi5lqzzd7Qisq7HId9YDX8on4' ],
                    CreateTime: [ '1560746323' ],
                    MsgType: [ 'text' ],
                    Content: [ '哈利路亚' ],
                    MsgId: [ '22344514908768682' ]
                }
            }*/
            // 格式化数据
            const message = formatMessage(jsData);
            console.log('格式化：');
            console.log(message);
            // 简单的自动回复， 回复文本内容
            /*  一旦遇到以下情况，微信都会在公众号会话中，向用户下发系统提示“该公众号暂时无法提供服务，请稍后再试”：
                1、开发者在5秒内未回复任何内容
                2、开发者回复了异常数据，比如JSON数据等。比如json数据、字符串、xml数据中有多余的空格***等
            */

            const options = reply(message);

            // 最终回复用户的消息
            const replyMessage = template(options);
            console.log(replyMessage);

            //如果开发者服务器没有响应给微信服务器， 其会发送三次请求过来
            // res.end('');
            res.send(replyMessage);
        } else {
            res.end('error');
        }

    }


}